package ecom.shell.commandsImpl;

import ecom.beans.EcomCustomerRemote;
import ecom.beans.ProductBean;
import ecom.beans.ProductstoreBean;
import ecom.beans.PurchaseBean;
import ecom.beans.exception.DeviseException;
import ecom.beans.exception.NotAccountAssociatedToUser;
import ecom.beans.exception.NotLoginException;
import ecom.shell.commandsImpl.OutputCommandImpl.Outputs;
import java.io.IOException;
import java.io.PrintStream;
import java.io.StringWriter;
import java.text.DecimalFormat;
import java.util.Set;
import java.util.StringTokenizer;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import shell.ShellCommand;
import shell.ShellContext;

public class CartCommandImpl implements ShellCommand {

    private ShellContext _context = null;

    public CartCommandImpl(ShellContext context) {
        _context = context;
    }

    @Override
    public String getName() {
        return "cart";
    }

    @Override
    public String getUsage() {
        return "cart";
    }

    @Override
    public String getShortDescription() {
        String commands = "Cart commands\n";
        commands += "\t-help ................................................get cart commands description\n";
        commands += "\t[without arg].........................................products in cart\n";
        commands += "\t-login [pseudo] [password]............................login to add products and buy the cart\n";
        commands += "\t-add [productstore ID] [product ID] [quantity]........add a specified quantity from cart\n";
        commands += "\t-remove [productstore ID] [product ID]................remove a product from cart\n";
        commands += "\t-update [productstore ID] [product ID] [quantity].....update a product quantity in the cart\n";
        commands += "\t-buy .................................................buy cart with a specified account\n";
        return commands;
    }

    @Override
    public String execute(String cmdline, PrintStream out, PrintStream err) {
        StringBuilder result = new StringBuilder();
        EcomCustomerRemote ecomCustomerBean = (EcomCustomerRemote) _context.getVar("customerBean");
        Outputs currentOutput = (Outputs) _context.getVar("output");
        String currentCurrency = (String) _context.getVar("currency");
        StringTokenizer cmd = new StringTokenizer(cmdline, " ");
        cmd.nextToken();

        if (cmd.countTokens() == 0) {
            try {
                return getCart(ecomCustomerBean, out, currentOutput, currentCurrency);
            } catch (Exception ex) {
                System.err.println("Error with getting all product in cart : " + ex.getMessage());
            }
        } else {
            String option = cmd.nextToken();
            try {
                if (option.equals("-help")) {
                    result.append(getShortDescription());
                } else if (option.equals("-login")) {
                    if (cmd.countTokens() == 2) {
                        String pseudo = cmd.nextToken();
                        String password = cmd.nextToken();

                        ecomCustomerBean.setUser(ecomCustomerBean.getUserByPseudoAndPassword(pseudo, password));
                        result.append("User login");
                    } else {
                        err.println(EcomCommandsConstantes.INCORRECT_NUMBER_ARGS);
                    }
                } else if (option.equals("-add")) {
                    if (cmd.countTokens() == 3) {
                        Long idProductstore = Long.valueOf(cmd.nextToken());
                        Long idProduct = Long.valueOf(cmd.nextToken());
                        Integer quantity = Integer.valueOf(cmd.nextToken());

                        ecomCustomerBean.addProductToCart(idProduct, idProductstore, quantity);
                        result.append("Product added to cart");
                    } else {
                        err.println(EcomCommandsConstantes.INCORRECT_NUMBER_ARGS);
                    }
                } else if (option.equals("-remove")) {
                    if (cmd.countTokens() == 2) {
                        Long idProductstore = Long.valueOf(cmd.nextToken().trim());
                        Long idProduct = Long.valueOf(cmd.nextToken().trim());

                        ecomCustomerBean.removeProductFromCart(idProduct, idProductstore);
                        result.append("Product removed to cart");
                    } else {
                        err.println(EcomCommandsConstantes.INCORRECT_NUMBER_ARGS);
                    }
                } else if (option.equals("-update")) {
                    if (cmd.countTokens() == 3) {
                        Long idProductstore = Long.valueOf(cmd.nextToken().trim());
                        Long idProduct = Long.valueOf(cmd.nextToken().trim());
                        Integer quantity = Integer.valueOf(cmd.nextToken().trim());

                        ecomCustomerBean.updateQuantityProduct(idProduct, idProductstore, quantity);
                        result.append("Product updated to cart");
                    } else {
                        err.println(EcomCommandsConstantes.INCORRECT_NUMBER_ARGS);
                    }
                } else if (option.equals("-buy")) {
                    ecomCustomerBean.buyCart();
                    result.append("CART BOUGHT");
                } else {
                    err.println(option + " is an unknown argument");
                }
            } catch (NotLoginException ex) {
                err.println("You have to login to add products and buy cart");
            } catch (NotAccountAssociatedToUser ex) {
                err.println("You don't have an account associated to your user account");
            } catch (NumberFormatException ex) {
                err.println("The args idProductstore, idProduct or quantity must be a number");
            } catch (Exception ex) {
                err.println("Error with Cart Management : " + ex);
            }
        }
        return result.toString();
    }

    private String getCart(EcomCustomerRemote ecomCustomerBean, PrintStream out, Outputs currentOutput, String currentCurrency) throws DeviseException, IOException {
        if (currentOutput.equals(Outputs.XML)) {
            return getXMLCart(ecomCustomerBean, out, currentCurrency);
        } else if (currentOutput.equals(Outputs.TEXT)) {
            return getTextCart(ecomCustomerBean, out, currentCurrency);
        } else {
            return ("Output format '" + currentOutput + "' is known but not implementing for this command");
        }
    }

    private String getTextCart(EcomCustomerRemote ecomCustomerBean, PrintStream out, String currentCurrency) throws DeviseException {
        StringBuilder res = new StringBuilder();
        DecimalFormat myFormatter = new DecimalFormat("##0.00");
        for (PurchaseBean purchase : ecomCustomerBean.getPurchasesInCart()) {
            res.append(purchase.toString()).append(" IN ").append(currentCurrency);
        }
        res.append("\nTotal : ").append(myFormatter.format(ecomCustomerBean.getCartTotalPriceInCurrentDevise(currentCurrency))).append(" ").append(currentCurrency);
        return res.toString();
    }

    public String getXMLCart(EcomCustomerRemote ecomCustomerBean, PrintStream out, String currentCurrency) throws DeviseException {
        Element cart = new Element("cart");
        Document document = new Document(cart);

        Element cartSate = new Element("state");
        cartSate.setText(String.valueOf(ecomCustomerBean.getCartState()));
        cart.addContent(cartSate);

        DecimalFormat myFormatter = new DecimalFormat("##0.00");

        for (PurchaseBean purchase : ecomCustomerBean.getPurchasesInCart()) {

            ProductBean p = purchase.getProductBean();
            ProductstoreBean productstore = purchase.getProductstoreBean();

            Element product = ProductCommandImpl.buildXMLProductNode(p);
            Element store = ProductstoreCommandImpl.buildXMLStoreNode(productstore, false, ecomCustomerBean, currentCurrency);
            product.addContent(store);
            cart.addContent(product);

            Element quantity = new Element("quantity");
            quantity.setText(String.valueOf(purchase.getQuantity()));
            product.addContent(quantity);

            Element price = new Element("price");
            price.setText(myFormatter.format(ecomCustomerBean.convertFromEuro(purchase.getPrice(), currentCurrency)));
            Attribute currency = new Attribute("currency", currentCurrency);
            price.setAttribute(currency);
            product.addContent(price);
        }

        Element totalAmount = new Element("total");
        totalAmount.setText(myFormatter.format(ecomCustomerBean.getCartTotalPriceInCurrentDevise(currentCurrency)));
        Attribute currency = new Attribute("currency", currentCurrency);
        totalAmount.setAttribute(currency);

        cart.addContent(totalAmount);

        XMLOutputter sortie = new XMLOutputter(Format.getPrettyFormat());
        return sortie.outputString(document);
    }

  }
